#include <stdlib.h>

#include "NWayTree.h"

/*
 * Public functions
 */

int treeInit(Tree *tree) {
    tree->root = createTreeNode();
    if (tree->root) {
        return 0;
    } else {
        return -1;
    }
}

int treeInsert(Tree *tree, long long int n) {
    TreeNode *current = tree->root;
    TreeNode *previous = NULL;
    unsigned short currentNibble;
    
    for (int i = 0; i < LEVELS - 1; i++) {
        currentNibble = getNibble(n, i);
        previous = current;
        current = current->pointers[currentNibble];
        if (NULL == current) {
            previous->pointers[currentNibble] = createTreeNode();
            current = previous->pointers[currentNibble];
        }
    }
    
    currentNibble = getNibble(n, LEVELS - 1);
    current->pointers[currentNibble] = (TreeNode *) 1;
    
    return 0;
}

int treeFind(Tree *tree, long long int n) {
    TreeNode *current = tree->root;
    unsigned short currentNibble;
    
    for (int i = 0; i < LEVELS - 1; i++) {
        currentNibble = getNibble(n, i);
        current = current->pointers[currentNibble];
        if (NULL == current) {
            return 0;
        }
    }
    
    currentNibble = getNibble(n, LEVELS - 1);
    if (NULL != current->pointers[currentNibble]) {
        return 1;
    } else {
        return 0;
    }
    
    return 0;
    
}

/*
 * Private functions
 */

TreeNode *createTreeNode() {
    TreeNode *treeNode = (TreeNode *) malloc(sizeof(TreeNode));
    
    if (NULL == treeNode) {
        return NULL;
    }
    
    for (int i = 0; i < POINTERS_PER_NODE; i++) {
        treeNode->pointers[i] = 0;
    }
    
    return treeNode;
}

unsigned char getNibble(unsigned long long number, int position) {
    return (number >> (position * BITS_PER_DECISION)) & BITMASK;
}
